package simmar.xcs;

import java.util.Random;
import java.util.List;
import java.util.Map;

import simmar.utilities.Logger;


public class XCSSubsumption implements XCSConfig
{
    private static Random randomNumber = new Random(System.currentTimeMillis());
    
    protected static void doActionSetSubsumption(
            List<XCSClassifier> actionSet, 
            Map<String,XCSClassifier> population
            )
    {
//        System.out.println("---------------------------------------------------------------------------------------------------------");
//        Logger.log("**** XCS DO ACTION SET SUBSUMPTION ****\n");
//        System.out.println("---------------------------------------------------------------------------------------------------------");
        
        XCSClassifier classifier = null;

        for (int i = 0; i < actionSet.size(); i++)
        {
            XCSClassifier nextClassifier = actionSet.get(i);
            
            if (couldSubsume(nextClassifier))
                if (classifier == null
                    || nextClassifier.getRule().getWildcardCount() > classifier.getRule().getWildcardCount()
                    || (nextClassifier.getRule().getWildcardCount() == classifier.getRule().getWildcardCount() && randomNumber.nextFloat() < 0.5f))
                    classifier = nextClassifier;
        }

        if (classifier != null)
        {
            for (int i = 0; i < actionSet.size(); i++)
            {
                XCSClassifier nextClassifier = actionSet.get(i);
                
                if (isMoreGeneral(classifier, nextClassifier))
                {
                    classifier.setNumerosity(classifier.getNumerosity() + nextClassifier.getNumerosity());
                    population.remove(actionSet.get(i).toString());
                    actionSet.remove(i);
                }
            }
        }
        
//        System.out.println("---------------------------------------------------------------------------------------------------------");
//        Logger.log("**** XCS DO ACTION SET SUBSUMPTION DONE ****\n");
//        System.out.println("---------------------------------------------------------------------------------------------------------");
    }

    protected static boolean couldSubsume(XCSClassifier classifier)
    {
//        System.out.println("---------------------------------------------------------------------------------------------------------");
//        Logger.log("**** XCS COULD SUBSUME ****\n");
//        System.out.println("---------------------------------------------------------------------------------------------------------");
        
        if (classifier.getExperience() > SUBSUMPTION_THRESHOLD)
            if (classifier.getAccuracy() > ACCURACY_THRESHOLD)
                return true;

        return false;
    }

    protected static boolean isMoreGeneral(XCSClassifier classifierA, XCSClassifier classifierB)
    {
//        System.out.println("---------------------------------------------------------------------------------------------------------");
//        Logger.log("**** XCS IS MORE GENERAL ****\n");
//        System.out.println("---------------------------------------------------------------------------------------------------------");
        
        if (classifierA.getRule().getWildcardCount() <= classifierB.getRule().getWildcardCount())
            return false;

        for (int i = 0; i < CONDITION_SIZE; i++)
        {
            if (classifierA.getRule().getConditionElement(i) != -1 && 
                classifierA.getRule().getConditionElement(i) != classifierB.getRule().getConditionElement(i))                
                return false;
        }

        return true;
    }

    protected static boolean doesSubsume(XCSClassifier classifierA, XCSClassifier classifierB)
    {
//        System.out.println("---------------------------------------------------------------------------------------------------------");
//        Logger.log("**** XCS DOES SUBSUME ****\n");
//        System.out.println("---------------------------------------------------------------------------------------------------------");
        
        if (classifierA.getRule().getAction() == classifierB.getRule().getAction())
            if (couldSubsume(classifierA))
                if (isMoreGeneral(classifierA, classifierB))
                    return true;

        return false;
    }
}